#ifndef TTHREAD_HEAD_
#define TTHREAD_HEAD_

#include <pthread.h>
#include <sched.h>
#include <assert.h>
#include <semaphore.h>
#include <time.h>
#include <errno.h>

typedef pthread_t	THREAD_HANDLE;

enum THREAD_BIND_STATUS
{
	THREAD_BIND		= PTHREAD_SCOPE_SYSTEM,		//°ó¶¨µÄÏß³Ì
	THREAD_NOT_BIND	= PTHREAD_SCOPE_PROCESS		//·Ç°ó¶¨µÄÏß³Ì
};
enum THREAD_DETACH_STATUS
{
	THREAD_DETACHED = PTHREAD_CREATE_DETACHED,	//·ÖÀëµÄÏß³Ì
	THREAD_JOINABLE	= PTHREAD_CREATE_JOINABLE	//²»·ÖÀëµÄÏß³Ì
};

typedef void * (*THREAD_ROUTINE)(void *);

struct ThreadAttr
{
	void *					args  ;
	THREAD_ROUTINE			fn  ;
	int						stack_size ;
	THREAD_DETACH_STATUS	status ;
	THREAD_BIND_STATUS		bind_status ;
	int						policy ;
	int						priority ;
	ThreadAttr()
	{
		args		= NULL ;
		stack_size	= 1024 * 1024;
		status		= THREAD_DETACHED;
		bind_status	= THREAD_BIND ;
		policy		= SCHED_OTHER;
		priority	= 0;

	}
};
//class IThreadPool;

//Ïß³ÌÀà
class TThread
{
public:
	TThread(void);
	//TThread( IThreadPool * pool )
	
public:
	virtual ~TThread(void);
	void *			  m_void ; //Ïß³ÌµÄ²ÎÊý

	//Æô¶¯Ïß³Ì
	/*
		args:	´«ÈëµÄ²ÎÊý
		fn:		Ö±½ÓÆô¶¯ÔËÐÐµÄÏß³Ìº¯Êý
		stack_size:¶ÑÕ»´óÐ¡Ä¬ÈÏ1M
		status		:·ÖÀëµÄ»ò·Ç·ÖÀëÊ½Ïß³Ì
		bind_status	:°ó¶¨µÄ»ò·Ç°ó¶¨µÄÏß³Ì
		policy		:¸ß¶È²ßÂÔ
		priority	£ºÓÅÏÈ¼¶

	*/
	bool	start_run( void * args  ,THREAD_ROUTINE fn  ,int stack_size  ,
		THREAD_DETACH_STATUS status ,THREAD_BIND_STATUS bind_status ,int policy = SCHED_OTHER ,int priority = 0 );

	bool	start_run( void * args = NULL ,THREAD_ROUTINE fn = NULL ,int stack_size = 1024 * 1024  ,THREAD_DETACH_STATUS status = THREAD_DETACHED  )
	{
			return start_run( args ,fn ,stack_size ,status ,THREAD_BIND ,SCHED_OTHER , 0 );
	}

	
		

	//Í£Ö¹Ïß³Ì
	void	stop_run();


protected:

	//Ïß³ÌÔËÐÐµÄº¯Êý
	virtual void  run ( void * object ) {} ;

	//Ïß³ÌÄÚ²¿ÔËÐÐµÄº¯Êý
	static void * thread_func( void * object );

	//ÉèÖÃÏß³ÌÓÅÏÈ¼¶
	bool	set_priority( int priority = 0 ,int policy = SCHED_OTHER );

private:
	THREAD_HANDLE     m_thread;	//Ïß³Ì¾ä±ú
	pthread_attr_t	  m_attr;
	//IThreadPool *	  m_thread_pool;
};



//Ëø½Ó¿ÚÀà
class TLock
{
public:
	TLock(void) { }

	//Ëø¶¨
	virtual void lock() = 0 ;

	//½âËø
	virtual void unlock() = 0 ;
public:
	virtual ~TLock(void){}
};

//×Ô¶¯ËøÀà
class TAutoLock
{
public:
	TAutoLock( TLock * lock ) {
		m_lock = lock ;
		m_lock->lock();
	}
public:
	virtual ~TAutoLock(void){
		m_lock->unlock();
	}
private:
	TLock * m_lock;
};

//ÎÞËøÀàÐÍ
class TNonLock: public TLock
{
public:
	TNonLock(void) { }

	//Ëø¶¨
	virtual void lock() { } ;

	//½âËø
	virtual void unlock() { };
public:
	virtual ~TNonLock(void){}
};

//»¥³âËøÀà
class TMutexLock : public TLock
{
public:
	TMutexLock(void)
	{
		 pthread_mutex_init( &m_mutex,  NULL );
		//rc == 0 ? true : false ;
	}
	virtual void lock()
	{
		pthread_mutex_lock( & m_mutex );
	}
	virtual void unlock()
	{
		pthread_mutex_unlock( &m_mutex );
	}
	pthread_mutex_t * get_handle(){ return &m_mutex ;}
public:
	virtual ~TMutexLock(void)
	{
		pthread_mutex_destroy( & m_mutex );
	}
private:
	pthread_mutex_t		m_mutex;
};

//¶ÁÐ´ËøÀà
class TRwLock : public TLock
{
public:
	TRwLock(void)
	{
		pthread_rwlock_init( &m_rwlock,  NULL );
		//rc == 0 ? true : false ;
	}

	//¶ÔÐ´Ëø½øÐÐËø¶¨
	virtual void lock()
	{
		pthread_rwlock_wrlock( & m_rwlock );
	}

	//¶Ô¶ÁËø½øÐÐËø¶¨
	virtual void rdlock()
	{
		pthread_rwlock_rdlock( & m_rwlock );
	}

	//½âËø
	virtual void unlock()
	{
		pthread_rwlock_unlock( &m_rwlock );
	}
public:
	virtual ~TRwLock(void)
	{
		pthread_rwlock_destroy( &m_rwlock );
	}
private:
	pthread_rwlock_t		m_rwlock;
};


//×ÔÐýËø
class TSpinlock : public TLock
{
public:
	TSpinlock(void)
	{
		pthread_spin_init( &m_spinlock,  0 );
		//rc == 0 ? true : false ;
	}
	//Ëø¶¨
	virtual void lock()
	{
		pthread_spin_lock( & m_spinlock );
	}
	//½âËø
	virtual void unlock()
	{
		pthread_spin_unlock( &m_spinlock );
	}
public:
	virtual ~TSpinlock(void)
	{
		pthread_spin_destroy( &m_spinlock );
	}
private:
	pthread_spinlock_t		m_spinlock;
};


//ÐÅºÅÁ¿
class TSem
{
public:
	TSem( ){ }
	TSem( int initvalue , int share ){
		sem_init( &m_sem , share , initvalue );
	}
	virtual ~TSem(){
		sem_destroy(&m_sem);
	}
public:

	//³õÊ¼»¯ÐÅºÅÁ¿ share ÊÇ·ñ½ø³Ì¹²Ïí,0²»¹²Ïí ,initvalue:³õÊ¼Öµ
	bool	init( int initvalue = 0 , int share = 0 )
	{
		return sem_init( &m_sem , share , initvalue ) == 0 ;
	}

	//·µ»Ø-1ÐÅºÅÁ¿Âú,¶ÔÐÅºÅÁ¿¼ÓÒ»²Ù×÷
	int	inc_sem()
	{
		return sem_post( &m_sem );
	}

	//»ñÈ¡ÐÅºÅÁ¿µÄ×ÜÊý
	int get_sem_value( )
	{
		int value = 0 ;
		sem_getvalue( &this->m_sem,&value);
		return value ;
	}

	//ÖØÉèÖÃÎª0ÐÅºÅ
	void reset()
	{
		int count = get_sem_value();
		for ( int i = 0 ; i < count ; i++)
			sem_wait( &m_sem );
	}

	//¶ÔÐÅºÅÁ¿¼õÒ»,²¢µÈ´ýÒ»¶¨Ê±¼ä ,timeout = -1 ±íÊ¾Ò»ÖµµÈ´ý
	int dec_sem( int timeout = -1 )
	{
		if ( timeout != -1 )
		{
			struct timespec ts;
			ts.tv_sec = /*time(NULL) +*/ timeout ;
			ts.tv_nsec = 0 ;
			int rc  = sem_timedwait( &m_sem , &ts );
			//int rc  = sem_reltimedwait_np( &m_sem , &ts );
			if ( rc != 0 )
			{
				if ( ETIMEDOUT == errno )
					return 1 ; //³¬Ê±
				else
					return 2 ;//ÆäËü´íÎó
			}
			return rc ; //³É¹¦
		}
		else
		{
			return  sem_wait( &m_sem );
		}
	}
private:
	sem_t	m_sem;

};

//Ìõ¼þ±äÁ¿
/*

/// ´¦ÀíÏß³Ì
pthread_mutex_lock(&mutex);            ///< 1
if (!test_cond)
{
pthread_cond_wait(&cond, &mutex);  ///< 2,3
}
pthread_mutex_unlock(&mutex);          ///< 4
RunThread1Func();

/// Ð´Ïß³Ì:
pthread_mutex_lock(&mutex);            ///< 5
test_cond = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);          ///< 6

*/
class TCondVar
{
public:
	TCondVar()
	{
		pthread_cond_init(&m_cond,NULL);
	}
	~TCondVar()
	{
		pthread_cond_destroy(&m_cond);
	}
	//Í¨ÖªÌõ¼þ±äÁ¿
	void broadcast(void)
	{
		pthread_cond_broadcast(&m_cond);
	}

	//µÈ´ýÌõ¼þ±äÁ¿
	void wait()
	{
		pthread_cond_wait(&m_cond,m_lock.get_handle());
	}

	//»¥³âËøËø¶¨
	void lock()
	{
		m_lock.lock();
	}

	//»¥³âËø½âËø
	void unlock()
	{
		m_lock.unlock();
	}
private:
	pthread_cond_t	m_cond;
	TMutexLock		m_lock;
};
#endif
